﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
 
namespace _4个红外测温仪
{
  
    public partial class Form1 : Form
    {
        public SerialPort serial1 = new SerialPort();//新建一个串口类
        bool isRUN = false;//串口状况
        public static Form2 f2 = new Form2();
       
        public static int Compensate1 = 0;
        public static int Compensate2 = 0;
        public static int Compensate3 = 0;
        public static int Compensate4 = 0;
        public class CustomComparer : System.Collections.IComparer
        {
            public int Compare(object x, object y)//比较两个字符串的长度
            {
                string s1 = (string)x;
                string s2 = (string)y;

                if (s1.Length > s2.Length) return 1;
                if (s1.Length < s2.Length) return -1;
                return s1.CompareTo(s2);
            }
        }
        public void serial1_send_data(byte[] buffer)//串口1的发送数据函数，串口1将分配给激光测距传感器
        {
            if (buffer.Length > 0)
            {
                if (serial1.IsOpen)
                {
                    serial1.Write(buffer, 0, buffer.Length);

                }
            }
        }
        public static bool ReceModbusDataIsTrue(byte[] Receive, int ReceiveNum)//判断微气象仪收到的帧是否为正确的
        {
            byte[] NeedToMakeCRCdata = new byte[ReceiveNum - 2];//C8 03 02 01 56 E5 FA 
            NeedToMakeCRCdata = Receive.Skip(0).Take(ReceiveNum - 2).ToArray();
            byte[] CRCresult = new byte[2];
            CRCresult = CRC16.CRCCalc(NeedToMakeCRCdata);
            if ((CRCresult[0] == Receive[ReceiveNum - 2]) && (CRCresult[1] == Receive[ReceiveNum - 1]))
            {
                return true;
            }
            return false;
        }
       
        public Form1()
        {
            InitializeComponent();

            this.StartPosition = FormStartPosition.CenterScreen;
            chart1.ChartAreas[0].AxisY.Minimum = 0;//设置chart的显示范围
            chart1.ChartAreas[0].AxisY.Maximum = 500;
            

           
        }
        public int CommunicationHasErr = 0;
        private void InvokeFun()
        {
            try
            {
                if (checkBox1.Checked == true)
                {
                    byte[] AskEquipmentTemperature = new byte[] { 0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A };
                    if (serial1.IsOpen)
                    {
                        AskEquipmentTemperature[0] = 6;//地址1
                        byte[] NeedToMakeCRCdata = new byte[6];
                        NeedToMakeCRCdata = AskEquipmentTemperature.Skip(0).Take(6).ToArray();
                        byte[] CRCresult = new byte[2];
                        CRCresult = CRC16.CRCCalc(NeedToMakeCRCdata);
                        AskEquipmentTemperature[6] = CRCresult[0];
                        AskEquipmentTemperature[7] = CRCresult[1];

                        serial1_send_data(AskEquipmentTemperature);
                        delaymS(800);
                        //Thread.Sleep(700);
                        int bytes = serial1.BytesToRead;

                        byte[] Recbuffer = new byte[7] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // 声明一个临时数组存储当前来的串口数据
                        if (bytes == 7)
                        {
                            try { serial1.Read(Recbuffer, 0, 7); } catch { };
                        }
                        else
                        {
                            int bytes_1 = serial1.BytesToRead;
                            byte[] DiscardBuffer_1 = new byte[bytes_1];
                            serial1.Read(DiscardBuffer_1, 0, bytes_1);
                        }
                        bool ReceEquipmentisTrue;
                        ReceEquipmentisTrue = ReceModbusDataIsTrue(Recbuffer, 7);
                        if ((ReceEquipmentisTrue == true) && (Recbuffer[1] == 0x03))
                        {
                            textBox1.Text = string.Format("{0:D4}", Recbuffer[3] * 256 + Recbuffer[4] + Compensate1);
                        }
                        else
                        {
                             CommunicationHasErr++;label7.Text = "地址6温度没读到！";
                            //MessageBox.Show("地址6温度没读到！", "warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            if (CommunicationHasErr > 5)
                            {   timer1.Enabled = false; button1_Click(null, new EventArgs());
                                MessageBox.Show("通讯失败了5次，即将关闭通讯！");
                            }
                            else { }
                        }
                    }
                    else
                    {
                        label7.Text = "串口没打开！";
                        //MessageBox.Show("串口没打开！");
                        //CommunicationHasErr++;
                        if (CommunicationHasErr > 5)
                        {
                            timer1.Enabled = false; button1_Click(null, new EventArgs());
                            MessageBox.Show("通讯失败了5次，即将关闭通讯！");
                        }
                        else { }
                    }
                }
                else
                {
                    textBox1.Text = Convert.ToString(Compensate1);
                }
                if (checkBox2.Checked == true)
                {
                    byte[] AskEquipmentTemperature = new byte[] { 0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A };
                    if (serial1.IsOpen)
                    {
                        AskEquipmentTemperature[0] = 7;//地址2
                        byte[] NeedToMakeCRCdata = new byte[6];
                        NeedToMakeCRCdata = AskEquipmentTemperature.Skip(0).Take(6).ToArray();
                        byte[] CRCresult = new byte[2];
                        CRCresult = CRC16.CRCCalc(NeedToMakeCRCdata);
                        AskEquipmentTemperature[6] = CRCresult[0];
                        AskEquipmentTemperature[7] = CRCresult[1];

                        serial1_send_data(AskEquipmentTemperature);
                        delaymS(800);
                        //Thread.Sleep(700);
                        int bytes = serial1.BytesToRead;
                        byte[] Recbuffer = new byte[7] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // 声明一个临时数组存储当前来的串口数据
                        if (bytes == 7)
                        {
                            try { serial1.Read(Recbuffer, 0, 7); } catch { };
                        }
                        else
                        {
                            int bytes_1 = serial1.BytesToRead;
                            byte[] DiscardBuffer_1 = new byte[bytes_1];
                            serial1.Read(DiscardBuffer_1, 0, bytes_1);
                        }
                        bool ReceEquipmentisTrue;
                        ReceEquipmentisTrue = ReceModbusDataIsTrue(Recbuffer, 7);
                        if ((ReceEquipmentisTrue == true) && (Recbuffer[1] == 0x03))
                        {
                            textBox2.Text = string.Format("{0:D4}", Recbuffer[3] * 256 + Recbuffer[4] + Compensate2);
                        }
                        else
                        {
                             CommunicationHasErr++; label7.Text = "地址7温度没读到！";
                            //MessageBox.Show("地址7温度没读到！", "warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            if (CommunicationHasErr > 5)
                            {   timer1.Enabled = false; button1_Click(null, new EventArgs());
                                MessageBox.Show("通讯失败了5次，即将关闭通讯！");
                            }
                            else { }

                        }
                    }
                    else
                    {
                        label7.Text = "串口没打开！";
                        //MessageBox.Show("串口没打开！"); 
                        CommunicationHasErr++;
                        if (CommunicationHasErr > 5)
                        {   timer1.Enabled = false; button1_Click(null, new EventArgs());
                            MessageBox.Show("通讯失败了5次，即将关闭通讯！");
                        }
                        else { }
                    }
                }
                else
                {
                    textBox2.Text = Convert.ToString(Compensate2);
                }
                if (checkBox3.Checked == true)
                {
                    byte[] AskEquipmentTemperature = new byte[] { 0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A };
                    if (serial1.IsOpen)
                    {
                        AskEquipmentTemperature[0] = 8;//地址1
                        byte[] NeedToMakeCRCdata = new byte[6];
                        NeedToMakeCRCdata = AskEquipmentTemperature.Skip(0).Take(6).ToArray();
                        byte[] CRCresult = new byte[2];
                        CRCresult = CRC16.CRCCalc(NeedToMakeCRCdata);
                        AskEquipmentTemperature[6] = CRCresult[0];
                        AskEquipmentTemperature[7] = CRCresult[1];

                        serial1_send_data(AskEquipmentTemperature);
                        delaymS(800);
                        //Thread.Sleep(700);
                        int bytes = serial1.BytesToRead;

                        byte[] Recbuffer = new byte[7] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // 声明一个临时数组存储当前来的串口数据
                        if (bytes == 7)
                        {
                            try { serial1.Read(Recbuffer, 0, 7); } catch { };
                        }
                        else
                        {
                            int bytes_1 = serial1.BytesToRead;
                            byte[] DiscardBuffer_1 = new byte[bytes_1];
                            serial1.Read(DiscardBuffer_1, 0, bytes_1);
                        }
                        bool ReceEquipmentisTrue;
                        ReceEquipmentisTrue = ReceModbusDataIsTrue(Recbuffer, 7);
                        if ((ReceEquipmentisTrue == true) && (Recbuffer[1] == 0x03))
                        {
                            textBox3.Text = string.Format("{0:D4}", Recbuffer[3] * 256 + Recbuffer[4] + Compensate3);
                        }
                        else
                        {
                             CommunicationHasErr++; label7.Text = "地址8温度没读到！";
                            //MessageBox.Show("地址8温度没读到！", "warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            if (CommunicationHasErr > 5)
                            {   timer1.Enabled = false; button1_Click(null, new EventArgs());
                                MessageBox.Show("通讯失败了5次，即将关闭通讯！");
                            }
                            else { }

                        }
                    }
                    else
                    {
                        label7.Text = "串口没打开！";
                        //MessageBox.Show("串口没打开！"); 
                        CommunicationHasErr++;
                        if (CommunicationHasErr > 5)
                        {   timer1.Enabled = false; button1_Click(null, new EventArgs());
                            MessageBox.Show("通讯失败了5次，即将关闭通讯！");
                        }
                        else { }
                    }
                }
                else
                {
                    textBox3.Text = Convert.ToString(Compensate3);
                }
                if (checkBox4.Checked == true)
                {
                    byte[] AskEquipmentTemperature = new byte[] { 0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A };
                    if (serial1.IsOpen)
                    {
                        AskEquipmentTemperature[0] = 9;//地址1
                        byte[] NeedToMakeCRCdata = new byte[6];
                        NeedToMakeCRCdata = AskEquipmentTemperature.Skip(0).Take(6).ToArray();
                        byte[] CRCresult = new byte[2];
                        CRCresult = CRC16.CRCCalc(NeedToMakeCRCdata);
                        AskEquipmentTemperature[6] = CRCresult[0];
                        AskEquipmentTemperature[7] = CRCresult[1];

                        serial1_send_data(AskEquipmentTemperature);
                        delaymS(800);
                        //Thread.Sleep(700);
                        int bytes = serial1.BytesToRead;

                        byte[] Recbuffer = new byte[7] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // 声明一个临时数组存储当前来的串口数据
                        if (bytes == 7)
                        {
                            try { serial1.Read(Recbuffer, 0, 7); } catch { };
                        }
                        else
                        {
                            int bytes_1 = serial1.BytesToRead;
                            byte[] DiscardBuffer_1 = new byte[bytes_1];
                            serial1.Read(DiscardBuffer_1, 0, bytes_1);
                        }
                        bool ReceEquipmentisTrue;
                        ReceEquipmentisTrue = ReceModbusDataIsTrue(Recbuffer, 7);
                        if ((ReceEquipmentisTrue == true) && (Recbuffer[1] == 0x03))
                        {
                            textBox4.Text = string.Format("{0:D4}", Recbuffer[3] * 256 + Recbuffer[4] + Compensate4);

                        }
                        else
                        {
                             CommunicationHasErr++; label7.Text = "地址9温度没读到！";
                            //MessageBox.Show("地址9温度没读到！", "warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            if (CommunicationHasErr > 5)
                            {   timer1.Enabled = false; button1_Click(null, new EventArgs());
                                MessageBox.Show("通讯失败了5次，即将关闭通讯！");
                            }
                            else { }
                        }
                    }
                    else
                    {
                        label7.Text = "串口没打开！";
                        //MessageBox.Show("串口没打开！"); 
                        CommunicationHasErr++;
                        if (CommunicationHasErr > 5)
                        {   timer1.Enabled = false;  button1_Click(null, new EventArgs());
                            MessageBox.Show("通讯失败了5次，即将关闭通讯！");
                        }
                        else { }

                    }
                }

                else
                {
                    textBox4.Text = Convert.ToString(Compensate4);
                }
                
            }
            catch
            {
            }
            
              
        
            

            chart1.Series[0].Points.Add(int.Parse(textBox1.Text));
            chart1.Series[1].Points.Add(int.Parse(textBox2.Text));
            chart1.Series[2].Points.Add(int.Parse(textBox3.Text));
            chart1.Series[3].Points.Add(int.Parse(textBox4.Text));

            if (chart1.Series[0].Points.Count > 20 | chart1.Series[1].Points.Count > 20 | chart1.Series[2].Points.Count > 20 | chart1.Series[3].Points.Count > 20)
            {
                chart1.Series[0].Points.RemoveAt(0);
                chart1.Series[1].Points.RemoveAt(0);
                chart1.Series[2].Points.RemoveAt(0);
                chart1.Series[3].Points.RemoveAt(0);
            }
            Write();
        }


        private void RS485Thread()
        {
            MethodInvoker mi = new MethodInvoker(this.InvokeFun);
            this.BeginInvoke(mi);
        }
        

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            CommunicationHasErr = 0;//将通讯错误复位
            
            if (isRUN == false)
            {
                label7.Text = "正在通讯中...";
                button1.Text = "关闭通信";
                isRUN = true;
                timer1.Enabled = true;
                try
                {
                    if (comboBox1.Text == "选择串口")
                    {
                    }
                    else
                    {
                        serial1.PortName = comboBox1.Text;
                        serial1.BaudRate = int.Parse("9600");
                        serial1.Parity = Parity.None;
                        serial1.DataBits = int.Parse("8");
                        serial1.StopBits = StopBits.One;
                        serial1.Open();

                    }

                }
                catch (Exception ex)
                {
                }
            }
            else
            {
                button1.Text = "开始通信";
                label7.Text = "通讯被关闭";

                isRUN = false;
                timer1.Enabled = false;
                serial1.Close();

            }

        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void comboBox1_DropDown(object sender, EventArgs e)
        {
            string port_name_old = comboBox1.Text;

            string[] port_names = SerialPort.GetPortNames();
            Array.Sort(port_names, new CustomComparer());
            comboBox1.Items.Clear();
            comboBox1.Items.AddRange(port_names);
            comboBox1.Items.Add("不选");


            if ((comboBox1.Items.Count > 0) && (comboBox1.SelectedIndex < 0))
            {
                comboBox1.SelectedIndex = 0;
            }
            comboBox1.Text = port_name_old;
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void checkBox3_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void checkBox4_CheckedChanged(object sender, EventArgs e)
        {

        }
        private void delaymS(double time)
        {
            double strart = Environment.TickCount;
            while (Math.Abs(Environment.TickCount - strart) < time)
            {
                Application.DoEvents();
            }
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
           /* if（Form2.CompensateCanBeRefresh == true）
            { 
            }
            else
            {

            }
            Form2.CompensateCanBeRefresh == false;*/
            Thread Thread = new Thread(RS485Thread);
            Thread.Start();
        }
        public static class CRC16
        {
            /// <summary>
            /// CRC校验，参数data为byte数组
            /// </summary>
            /// <param name="data">校验数据，字节数组</param>
            /// <returns>字节0是高8位，字节1是低8位</returns>
            public static byte[] CRCCalc(byte[] data)
            {
                //crc计算赋初始值
                int crc = 0xffff;
                for (int i = 0; i < data.Length; i++)
                {
                    crc = crc ^ data[i];
                    for (int j = 0; j < 8; j++)
                    {
                        int temp;
                        temp = crc & 1;
                        crc = crc >> 1;
                        crc = crc & 0x7fff;
                        if (temp == 1)
                        {
                            crc = crc ^ 0xa001;
                        }
                        crc = crc & 0xffff;
                    }
                }
                //CRC寄存器的高低位进行互换
                byte[] crc16 = new byte[2];
                //CRC寄存器的高8位变成低8位，
                crc16[1] = (byte)((crc >> 8) & 0xff);
                //CRC寄存器的低8位变成高8位
                crc16[0] = (byte)(crc & 0xff);
                return crc16;
            }

            /// <summary>
            /// CRC校验，参数为空格或逗号间隔的字符串
            /// </summary>
            /// <param name="data">校验数据，逗号或空格间隔的16进制字符串(带有0x或0X也可以),逗号与空格不能混用</param>
            /// <returns>字节0是高8位，字节1是低8位</returns>
            public static byte[] CRCCalc(string data)
            {
                //分隔符是空格还是逗号进行分类，并去除输入字符串中的多余空格
                IEnumerable<string> datac = data.Contains(",") ? data.Replace(" ", "").Replace("0x", "").Replace("0X", "").Trim().Split(',') : data.Replace("0x", "").Replace("0X", "").Split(' ').ToList().Where(u => u != "");
                List<byte> bytedata = new List<byte>();
                foreach (string str in datac)
                {
                    bytedata.Add(byte.Parse(str, System.Globalization.NumberStyles.AllowHexSpecifier));
                }
                byte[] crcbuf = bytedata.ToArray();
                //crc计算赋初始值
                return CRCCalc(crcbuf);
            }

            /// <summary>
            ///  CRC校验，截取data中的一段进行CRC16校验
            /// </summary>
            /// <param name="data">校验数据，字节数组</param>
            /// <param name="offset">从头开始偏移几个byte</param>
            /// <param name="length">偏移后取几个字节byte</param>
            /// <returns>字节0是高8位，字节1是低8位</returns>
            public static byte[] CRCCalc(byte[] data, int offset, int length)
            {
                byte[] Tdata = data.Skip(offset).Take(length).ToArray();
                return CRCCalc(Tdata);
            }
        }
        public void Write()//在CSV表里写一行数据
        {
            string path = System.AppDomain.CurrentDomain.BaseDirectory + "历史数据/" + "温度数据" + DateTime.Now.ToString("yyyy" + "年" + "MM" + "月" + "dd" + "日") + ".csv";//"红外测温探头数据.csv";
            if (!File.Exists(path))
                File.Create(path).Close();

            StreamWriter sw = new StreamWriter(path, true, Encoding.UTF8);
            var time = DateTime.Now.ToString("yyyy" + "年" + "MM" + "月" + "dd" + "日" + "HH" + "时" + "mm" + "分" + "ss" + "秒");

            sw.Write(textBox1.Text + ",");//1号
            sw.Write(textBox2.Text + ",");//2号
            sw.Write(textBox3.Text + ",");//3号
            sw.Write(textBox4.Text + ",");//4号
            
            sw.Write(time + "\r\n");//数据的日期时间


            sw.Flush();
            sw.Close();
        }
       
        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }
         
        private void Form1_Load(object sender, EventArgs e)
        {
            
            comboBox1.Items[0] = Properties.Settings.Default.InfraredCOM;
            Compensate1= Properties.Settings.Default.Compensate1;
            Compensate2 = Properties.Settings.Default.Compensate2;
            Compensate3 = Properties.Settings.Default.Compensate3;
            Compensate4 = Properties.Settings.Default.Compensate4;
        }
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            Properties.Settings.Default.InfraredCOM = comboBox1.Text;
            Properties.Settings.Default.Save();

            serial1.Close();//退出时释放串口
            Environment.Exit(0);
            Process.GetCurrentProcess().Kill();
        }

        private void chart1_Click(object sender, EventArgs e)
        {

        }

        private void textBox4_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Form3 f3 = new Form3();
            f3.StartPosition = FormStartPosition.CenterScreen;
            f3.Show();
            
        }

        private void label27_Click(object sender, EventArgs e)
        {

        }

        private void label28_Click(object sender, EventArgs e)
        {

        }

        private void txtPath_TextChanged(object sender, EventArgs e)
        {

        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }
        private bool information = false;
        private void label6_Click(object sender, EventArgs e)
        {
            if (information == false)
            {
                label6.Text = "株洲三江电子\n保留版权 C_博\n296930009@qq.com";
                information = true;
            }
            else
            {
                label6.Text = "关于作者";
                information = false;
            }
            
        }

        private void label5_Click(object sender, EventArgs e)
        {

        }
        public bool FormIsShow = false;


       
        private void button3_Click(object sender, EventArgs e)
        {
           
            if (FormIsShow == false)
            {
                f2.StartPosition = FormStartPosition.CenterScreen;
                f2.Show();
                button3.Text = "关闭";
                FormIsShow = true;
            }
            else
            {
                f2.label9.Text = "待确认";
                f2.label10.Text = "待确认";
                f2.label11.Text = "待确认";
                f2.label12.Text = "待确认";
                f2.Hide();
                button3.Text = "补偿";
                FormIsShow = false;
            
            }
        }

        private void label5_Click_1(object sender, EventArgs e)
        {

        }
    }
}
